﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace BarcodeDelay.Transaction
{
    public class DbOperatorFactory
    {
        private String connectionString;
        private String dbProvider;
        private String poolName;
        private DbProviderFactory dbProviderFactory;
        public event EventHandler<EargsGetDbOperator> OnGetDbOperatorEvent;
        public event EventHandler<EargsReleaseDbOperator> OnReleaseDbOperatorEvent;

        /// <summary>
        /// Init
        /// </summary>
        /// <param name="_connectionString"></param>
        /// <param name="_poolName"></param>
        public void Init(String _connectionString, String _provider, String _poolName)
        {
            this.connectionString = _connectionString;
            this.dbProvider = _provider;
            this.poolName = _poolName;
            try
            {
                this.dbProviderFactory = DbProviderFactories.GetFactory(this.dbProvider);
            }
            catch (System.Exception ex)
            {
                //SimbaCameraScale.Common.Log.Logger.LogError("DbConnPool", ex.Message);
            }
        }

        private DbConnection CreateDbConnection()
        {
            string dir = System.Environment.CurrentDirectory;
            DbConnection connection = this.dbProviderFactory.CreateConnection();
            if (connection == null)
            {
                StreamWriter swb2 = new StreamWriter(dir + "\\task.txt", true);
                swb2.WriteLine(System.DateTime.Now + "connection==null：");
                swb2.Close();

                return connection;
            }
            if (connection == null)
            {
                connection = this.dbProviderFactory.CreateConnection();
                connection.ConnectionString = connectionString;
            }

            try
            {                             
                connection.ConnectionString = connectionString;
                connection.Open();
            }
            catch (System.Exception ex)
            {
                
                StreamWriter swb = new StreamWriter(dir + "\\task.txt", true);
                swb.WriteLine(System.DateTime.Now + "CreateDbConnection error：" + ex.ToString());
                swb.Close();
                StoParams.Instance.isDbConnect = false;
                //Logger.LogError("DbConnPool", "【Database】： Catch an exception : " + ex.Message);
                connection = null;
            }

            return connection;
        }

        /// <summary>
        /// ShutDown
        /// </summary>
        public void ShutDown()
        {
        }

        /// <summary>
        /// Get a Database connection from the pool
        /// </summary>
        /// <returns></returns>
        public DbOperator CreateDbOperator()
        {
            DbOperator dbOperator = null;

            try
            {
                DbConnection connection = this.CreateDbConnection();

                if (connection == null || (connection.State != ConnectionState.Open))
                {
                    return dbOperator;
                }

                dbOperator = new DbOperator(this, connection);
                dbOperator.Name = "DBOP-" + this.poolName;
            }
            catch (System.Exception ex)
            {
                //Logger.LogError("DbConnPool", "【Database】： Catch an exception : " + ex.Message);
            }

            return dbOperator;
        }

        //////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Pool Name
        /// </summary>
        public string PoolName { get { return this.poolName; } }

        /// <summary>
        /// Send dboperator get message to the interesting component
        /// </summary>
        /// <param name="operatorName"></param>
        private void TriggerGetOperatorEvent(string operatorName)
        {
            try
            {
                if (this.OnGetDbOperatorEvent != null)
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(DoTriggerGetOperatorEvent), operatorName);
                }
            }
            catch (System.Exception ex)
            {
                //Logger.LogError("TriggerGetOperatorEvent", "Catch an exception :" + ex.Message);
            }
        }

        private void DoTriggerGetOperatorEvent(Object operatorNameObj)
        {
            String operatorName = operatorNameObj as String;

            EargsGetDbOperator args = new EargsGetDbOperator();
            args.OperatorName = operatorName;
            //EventHandlerTrigger.TriggerEvent<EargsGetDbOperator>(this.OnGetDbOperatorEvent, this, args);
        }

        /// <summary>
        /// Send dboperator release message to the interesting component
        /// </summary>
        /// <param name="operatorName"></param>
        private void TriggerReleaseOperatorEvent(string operatorName)
        {
            try
            {
                if (this.OnReleaseDbOperatorEvent != null)
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(DoTriggerReleaseOperatorEvent), operatorName);
                }
            }
            catch (System.Exception ex)
            {
                //Logger.LogError("TriggerReleaseOperatorEvent", "Catch an exception :" + ex.Message);
            }
        }

        private void DoTriggerReleaseOperatorEvent(Object operatorNameObj)
        {
            String operatorName = operatorNameObj as String;

            EargsReleaseDbOperator args = new EargsReleaseDbOperator();
            args.OperatorName = operatorName;
            //EventHandlerTrigger.TriggerEvent<EargsReleaseDbOperator>(this.OnReleaseDbOperatorEvent, this, args);
        }

        public DbProviderFactory DbProviderFactory
        {
            get { return this.dbProviderFactory; }
        }
        //////////////////////////////////////////////////////////////////////////End Of Class
    }
}

